package com.yygo.webapp.controller;

import com.yygo.Constants;
import com.yygo.model.*;
import com.yygo.service.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

@Controller
@RequestMapping("/dealerform*")
public class DealerFormController extends BaseFormController {
    private DealerManager dealerManager = null;
    @Autowired
    private ProvinceManager provinceManager;

    @Autowired
    private LoanProductManager loanProductManager;

    @Autowired
    private BondManager bondManager;

    @Autowired
    private RoleManager roleManager;

    @Autowired
    public void setDealerManager(@Qualifier("dealerManager") DealerManager dealerManager) {
        this.dealerManager = dealerManager;
    }

    public DealerFormController() {
        setCancelView("redirect:/dealers");
        setSuccessView("redirect:/dealers");
    }

    @ModelAttribute
    @RequestMapping(method = RequestMethod.GET)
    protected Dealer showForm(HttpServletRequest request)
    throws Exception {
        String id = request.getParameter("dealerId");
        Dealer dealer = null;
        if (!StringUtils.isBlank(id)) {
            dealer = dealerManager.get(new Long(id));
        } else {
            dealer = new Dealer();
            String bondId = request.getParameter("bondId");
            if (!StringUtils.isBlank(bondId)) {
                BondCompany bond = bondManager.get(new Long(bondId));
                dealer.setBond(bond);
            } else {
                throw new IllegalAccessException("illegal access: bond id is empty.");
            }
        }

        return dealer;
    }

    @RequestMapping(method = RequestMethod.POST)
    public String onSubmit(Dealer dealer, BindingResult errors, HttpServletRequest request,
                           HttpServletResponse response)
    throws Exception {
        if (dealer.getBond().getId() == null) {
            throw new IllegalAccessException("illegal access: bank id is empty.");
        } else {
            BondCompany bond = bondManager.get(dealer.getBond().getId());
            dealer.setBond(bond);
        }

        String from = request.getParameter("from");

        if (request.getParameter("cancel") != null) {
            if (from.equals("bond"))
                return "redirect:/bondCompanyform?id=" + dealer.getBond().getId();
            else //if (from.equals("list"))
                return "redirect:/dealers";
        }

        if (validator != null) { // validator is null during testing
            validator.validate(dealer, errors);

            if (errors.hasErrors() && request.getParameter("delete") == null) { // don't validate when deleting
                return "dealerform";
            }
        }

        log.debug("entering 'onSubmit' method...");

        boolean isNew = (dealer.getId() == null);
        String success = "redirect:/bondCompanyform?id=" + dealer.getBond().getId();
        if (from.equals("list"))
            success = "redirect:/dealers";

        Locale locale = request.getLocale();

      if(dealer.getSlaveProviderId()!=null){
        dealer.setSlaveProvider(bondManager.get(dealer.getSlaveProviderId()));
      }

      if(dealer.getMasterProviderId()!=null){
        dealer.setMasterProvider((bondManager.get(dealer.getMasterProviderId())));
      }
        if (request.getParameter("delete") != null) {
            dealerManager.remove(dealer.getId());
            saveMessage(request, getText("dealer.deleted", locale));
        } else {
            User user = dealer.getAdminUser();
            User nameUser = getUserManager().getUserByUsername(user.getUsername());
            User emailUser = getUserManager().getUserByEmail(user.getEmail());
            if (nameUser!=null && nameUser.getId()!=user.getId()){
                errors.rejectValue("adminUser.username", "errors.username.exist", new String[]{user.getUsername()}, "username is exist");
            }
            if (emailUser!=null && emailUser.getId()!=user.getId()){
                errors.rejectValue("adminUser.email", "errors.email.exist", new String[]{user.getEmail()}, "email is exist");
            }
            if (errors.hasErrors()) {
                copyErrors(request, errors);
                return "dealerform";
            }
            user.setEnabled(true);
            user.getRoles().clear();
            user.addRole(roleManager.getRole(Constants.DEALER_USER_ROLE));
            user.addRole(roleManager.getRole(Constants.DEALER_ADMIN_ROLE));
            User adminUser = getUserManager().saveUser(user);
            dealer.setAdminUser(adminUser);
            dealer.getUsers().add(adminUser);
            dealer = dealerManager.save(dealer);
            adminUser.setDealer(dealer);
            getUserManager().save(adminUser);

            String key = (isNew) ? "dealer.added" : "dealer.updated";
            saveMessage(request, getText(key, locale));

            if (!isNew)
                success = "redirect:/dealerform?dealerId=" + dealer.getId() + "&from=" + from;
        }

        return success;

    }

    private void copyErrors(HttpServletRequest request, BindingResult errors) {
        List<ObjectError> errorMessages = errors.getAllErrors();
        for (ObjectError err : errorMessages) {
            saveError(request, getText(err.getCode(), err.getArguments(), request.getLocale()));
        }
    }

  @ModelAttribute("availableSlaveProviders")
  protected List<LabelValue> getAvailableSlaveProviders(){
    List<LabelValue> list = new ArrayList<LabelValue>();
    List<BondCompany> bondCompanies = bondManager.getAll();
    for (BondCompany bondCompany : bondCompanies) {
      if(bondCompany.isSlaveProvider()) {
        list.add(new LabelValue(bondCompany.getName(), ""+bondCompany.getId()));
      }
    }
    return list;
  }
  @ModelAttribute("availableMasterProviders")
  protected List<LabelValue> getAvailableMasterProviders(){
    List<LabelValue> list = new ArrayList<LabelValue>();
    List<BondCompany> bondCompanies = bondManager.getAll();
    for (BondCompany bondCompany : bondCompanies) {
      if(bondCompany.isMasterProvider()) {
        list.add(new LabelValue(bondCompany.getName(), ""+bondCompany.getId()));
      }
    }
    return list;
  }
    @ModelAttribute("availableProvinces")
    protected List<LabelValue> getAvailableProvinces() {
        List<LabelValue> list = new ArrayList<LabelValue>();
        List<Province> provinces = provinceManager.getAll();
        for (Province province : provinces) {
            list.add(new LabelValue(province.getName(), province.getName()));
        }
        return list;
    }

    @ModelAttribute("availableRiskRanks")
    protected List<LabelValue> loadAvailableRiskRanks() {
        return getList(Constants.RISK_RANK);
    }

    @ModelAttribute
    protected List<User> getUsers(HttpServletRequest request)
            throws Exception {
        String id = request.getParameter("dealerId");

        if (!StringUtils.isBlank(id)) {
            return dealerManager.getUsers(new Long(id));
        }

        return new ArrayList<>();
    }

    @ModelAttribute
    protected Set<DealerRule> getDealerRules(HttpServletRequest request)
            throws Exception {
        String dealerId = request.getParameter("dealerId");
        if (!StringUtils.isBlank(dealerId)) {
            Dealer dealer = dealerManager.get(new Long(dealerId));
            return dealer.getDealerRules();
        }
        return new HashSet<>();
    }

}
